Skip to content

Fail instead of silently dropping Plutus scripts the era does not support - #1363

Merged
carbolymer merged 1 commit into
masterfrom
mgalazyn/fix/unsupported-plutus-language-error
Oct 9, 2026
Merged

carbolymer merged 1 commit into
masterfrom
mgalazyn/fix/unsupported-plutus-language-error

Conversation

@carbolymer

@carbolymer carbolymer commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Plutus scripts in a language the era does not support are rejected instead of being dropped.

In the experimental API the check happens where the bytes enter.
decodeAnyPlutusScript and deserialiseAnyPlutusScriptFromTextEnvelope fail with a decoder error that names the language and the era.
PlutusScriptInEra can only be built for a pairing the ledger supports: mkPlutusScriptInEra, deserialisePlutusScriptInEra and deserialiseAnyPlutusScriptOfLanguage take the ledger's EraPlutusTxInfo lang era constraint, and so do its SerialiseAsCBOR and HasTextEnvelope instances, so a wrong pairing is a compile error.
PlutusLangInEra lang era is the runtime proof returned by plutusLangInShelleyBasedEra and plutusLangInEra, which ask the ledger's mkSupportedLanguage; cardano-api keeps no table of languages per era.
PlutusScriptInEra also holds the ledger script, built once through the ledger's mkSupportedPlutusScript, so no later conversion can fail and fromPlutusRunnable is gone.
This is a breaking change to the experimental API: PlutusScriptInEra gains a field and a constraint, deserialisePlutusScriptInEra and deserialiseAnyPlutusScriptOfLanguage lose their language argument, and decodeAnyPlutusScript and deserialiseAnyPlutusScriptFromTextEnvelope now require IsShelleyBasedEra for the api era that matches the ledger era.

In the legacy API, createTransactionBody fails with TxOutputReferenceScriptLanguageNotSupportedInEra when an output or the return collateral carries a reference script in a language the era does not support.
The test generators take the supported Plutus languages from scriptLanguageSupportedInEra, and the Plutus V4 fixture is a validator compiled against Plutus V4.

Context

The experimental part follows the design Jordan proposed on this PR and prepared in PR 1372, folded in here:

Known gap, outside this PR:

How to trust this PR

prop_deserialise_rejects_unsupported_plutus_language checks that V4 bytes fail to decode in Conway with the error naming the era.
prop_makeUnsignedTx_accepts_reference_plutus_v4_witness checks that a reference witness still passes.
prop_createTransactionBody_rejects_unsupported_reference_script_language checks the legacy reference script path.
A test that builds a Plutus V4 inline witness in Conway no longer typechecks, which is the point of the change.

Checklist

  • Commit sequence broadly makes sense and commits have useful messages
  • New tests are added if needed and existing tests are updated. See Running tests for more details
  • Self-reviewed the diff
  • Changelog fragment added in .changes/

@carbolymer
carbolymer added this pull request to stack #1364 September 30, 2026 13:48
@carbolymer carbolymer changed the title Fail instead of silently dropping Plutus scripts unsupported by the era Reject Plutus scripts unsupported by the era instead of silently dropping them Sep 30, 2026
@carbolymer carbolymer self-assigned this Sep 30, 2026
@carbolymer
carbolymer force-pushed the mgalazyn/fix/unsupported-plutus-language-error branch 2 times, most recently from 1c03d44 to ed67933 Compare October 1, 2026 19:25
@carbolymer carbolymer changed the title Reject Plutus scripts unsupported by the era instead of silently dropping them Fail instead of silently dropping Plutus scripts the era does not support Oct 1, 2026
@carbolymer
carbolymer force-pushed the mgalazyn/fix/unsupported-plutus-language-error branch from ed67933 to 62d4680 Compare October 1, 2026 20:13
@carbolymer
carbolymer marked this pull request as ready for review October 1, 2026 20:13
Copilot AI balanced review requested due to automatic review settings October 1, 2026 20:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The dependency bump is misclassified and the experimental API migration note inaccurately describes two previous return types.

Review effort: Balanced
Findings: 3 Low severity

Open (3)
What changed in this PR

Prevents unsupported Plutus scripts from being silently omitted during transaction construction.

Changes:

  • Returns explicit errors for unsupported witness and reference-script languages.
  • Adds regression tests, V4 fixtures, and golden output.
  • Updates Plutus dependencies and changelog fragments.
File Description
flake.lock Updates the CHaP revision.
cardano-api/​test/​cardano-api-test/​Test/​Cardano/​Api/​Transaction/​Body/​Plutus/​Scripts.hs Adds unsupported-language regression tests.
cardano-api/​test/​cardano-api-golden/​Test/​Golden/​ErrorsSpec.hs Adds the new output-error golden case.
cardano-api/​test/​cardano-api-golden/​files/​errors/​Cardano.Api.Tx.Body.TxBodyError/​TxBodyOutputReferenceScriptLanguageNotSupportedInEra.txt Records the new error message.
cardano-api/​src/​Cardano/​Api/​Tx/​Internal/​Output.hs Validates output reference-script languages.
cardano-api/​src/​Cardano/​Api/​Tx/​Internal/​Body.hs Applies validation during body creation.
cardano-api/​src/​Cardano/​Api/​Experimental/​Tx/​Internal/​TxScriptWitnessRequirements.hs Propagates unsupported-language failures.
cardano-api/​src/​Cardano/​Api/​Experimental/​Tx/​Internal/​BodyContent/​New.hs Adds and returns the unsigned-transaction error.
cardano-api/​src/​Cardano/​Api/​Experimental/​Tx/​Internal/​AnyWitness.hs Changes script extraction to Either.
cardano-api/​src/​Cardano/​Api/​Experimental/​Plutus/​Internal/​Shim/​LegacyScripts.hs Adapts legacy witness conversion.
cardano-api/​src/​Cardano/​Api/​Experimental/​AnyScriptWitness.hs Detects unsupported inline script languages.
cardano-api/​gen/​Test/​Gen/​Cardano/​Api/​Typed.hs Restricts generation to supported languages.
cardano-api/​gen/​Test/​Gen/​Cardano/​Api/​Hardcoded.hs Adds Plutus V4 fixtures.
cardano-api/​cardano-api.cabal Requires Plutus 1.71 dependencies.
cabal.project Advances the CHaP index state.
.changes/​plutus-1-71-bump.yml Documents the dependency bump.
.changes/​legacy-tx-body-unsupported-reference-script-language-error.yml Documents the legacy API break.
.changes/​experimental-tx-unsupported-plutus-language-error.yml Documents the experimental API break.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

description: |
`makeUnsignedTx` now fails with `MakeUnsignedTxPlutusLanguageNotSupportedInEra` when an inline Plutus script uses a language the era does not support.
Before, the script was silently dropped from the witness set while its redeemer was kept, so the transaction failed on submission.
`getAnyWitnessScript`, `getAnyPlutusWitnessPlutusScript`, `getTxScriptWitnessRequirements` and `getTxScriptWitnessesRequirements` now return `Either L.Language` instead of `Maybe`.
Comment thread .changes/plutus-1-71-bump.yml Outdated
Comment on lines +228 to +229
-- | An inline Plutus witness must be rejected, not silently dropped with its
-- redeemer, when the era does not support its language. V4 fails in Conway.
@Jimbo4350

Copy link
Copy Markdown
Contributor

What about this approach? master...jordan/plutus-language-in-era-vs-master

@carbolymer
carbolymer force-pushed the mgalazyn/fix/unsupported-plutus-language-error branch 2 times, most recently from 4f7d365 to b2764fd Compare October 7, 2026 13:33
@carbolymer
carbolymer force-pushed the mgalazyn/fix/unsupported-plutus-language-error branch 4 times, most recently from 54a1fbb to 5f5de62 Compare October 8, 2026 13:50

@Jimbo4350 Jimbo4350 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I have one further small simplification to suggest: mgalazyn/fix/unsupported-plutus-language-error...jordan/plutus-script-in-era-single-field

@carbolymer
carbolymer force-pushed the mgalazyn/fix/unsupported-plutus-language-error branch from 5f5de62 to 1833ae9 Compare October 9, 2026 06:29
…port

Plutus scripts in a language the era does not support are rejected instead of being dropped.

In the experimental API the check happens where the bytes enter.
decodeAnyPlutusScript and deserialiseAnyPlutusScriptFromTextEnvelope fail with a decoder error that names the language and the era.
PlutusScriptInEra carries the ledger's EraPlutusTxInfo lang era evidence in its constructor, so it exists only for a pairing the ledger supports and converts to the ledger script through mkSupportedPlutusScript without a partial step.
deserialisePlutusScriptInEra and deserialiseAnyPlutusScriptOfLanguage take that constraint instead of a language singleton, and so do the SerialiseAsCBOR and HasTextEnvelope instances of PlutusScriptInEra.
PlutusLangInEra lang era is the runtime proof, returned by plutusLangInShelleyBasedEra and plutusLangInEra, which ask the ledger's mkSupportedLanguage; cardano-api keeps no table of languages per era.
The legacy shim looks the language up at runtime, and the Either L.Language results and MakeUnsignedTxPlutusLanguageNotSupportedInEra are gone.

In the legacy API, createTransactionBody fails with TxOutputReferenceScriptLanguageNotSupportedInEra when an output or the return collateral carries a reference script in a language the era does not support.
Before, the output was built without the script and no error was reported.
The test generators take the supported Plutus languages from scriptLanguageSupportedInEra, and the Plutus V4 fixture is a validator compiled against Plutus V4.

Co-authored-by: Jordan Millar <jordan.millar@iohk.io>
@carbolymer
carbolymer force-pushed the mgalazyn/fix/unsupported-plutus-language-error branch from 1833ae9 to cfcc6e2 Compare October 9, 2026 06:30
@carbolymer

carbolymer commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor Author

@Jimbo4350 makes sense, thanks! I've used it 👍🏻

@carbolymer
carbolymer added this pull request to the merge queue Oct 9, 2026
Merged via the queue into master with commit 65205dc Oct 9, 2026
34 checks passed
carbolymer added a commit that referenced this pull request Oct 9, 2026
…lutus-language-error

Fail instead of silently dropping Plutus scripts the era does not support
@carbolymer
carbolymer deleted the mgalazyn/fix/unsupported-plutus-language-error branch October 9, 2026 07:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants